package com.ebspp.client.serverManager;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

import com.ebspp.thrift.DataMsg;
import com.ebspp.thrift.DataRead;
import com.ebspp.thrift.Identity;
import com.ebspp.thrift.ResourceType;

/**
 * Read connection, used to read data from servers.
 * It will try to provision some resources as write do.
 * If the server returns IP of itself for the provision call, the provision success
 * If the server returns IP of another server, the provision success, you should read for the new server
 * If the server returns null. the provision fails, no read is permissible.
 * 
 * Note the server will try its best to serve the read.
 * A fail provision probably means the call parameters are wrong.
 * 
 * @author x23pan
 *
 */
public class ReadConnection 
{
	private String server;
	private int rPort;
	private Identity id;
	private ResourceType resType;
	
	private DataRead.Client rClient;
	private TTransport transport;
	
	Object mutex = new Object();
	private IStat stat;
	int resource = 0;
	
	public ReadConnection(String server, int rPort, ResourceType resType, Identity id, IStat stat)
	{
		this.server = server;
		this.rPort = rPort;
		this.resType = resType;
		this.id = id;
		
		this.stat = stat;
	}
	
	public void connect() throws TTransportException
	{
		transport = new TSocket(server, rPort);
		//TTransport wTransport = new TFramedTransport(socket);
		TProtocol protocol = new TBinaryProtocol(transport);
		rClient = new DataRead.Client(protocol);
		transport.open();
	}
	
	public void close()
	{
		transport.close();
	}
	
	public List<DataMsg> read(List<DataMsg> keys) throws TException
	{
		synchronized(mutex)
		{
			return rClient.readEBSPP(keys, resType, id);
		}
	}
	//provision resources
	public String provision(int amount) throws TException
	{
		Map<ResourceType, Integer> askRes = new HashMap<ResourceType, Integer>();
		askRes.put(resType, amount);
		String candidate;
		synchronized(mutex)
		{
			candidate = rClient.provision(askRes, id);
		}
		if(candidate != null)
			resource += amount;
		return candidate;
	}
	
	public String getServer()
	{
		return server;
	}
	public int getResource()
	{
		return resource;
	}
	
	
	public boolean equals(Object obj)
	{
		if(obj == null)
			return false;
		if(obj instanceof ReadConnection)
		{
			ReadConnection conn = (ReadConnection)obj;
			if(id.equals(conn.id) && server.equals(conn.server) && resType.equals(conn.resType))
				return true;
		}
		return false;
	}
	
	public int hashCode()
	{
		return id.hashCode() * 3 + server.hashCode() * 13 + resType.hashCode() * 17;
	}
}
